<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml">
  <head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
    
    <title>Places To Go</title>
    
    <link href="http://www.google.com/uds/css/gsearch.css" type="text/css" rel="stylesheet"/>
    <link href="ConcreteJungle.css" type="text/css" rel="stylesheet"/>
	
	<!-- IMPORTANT, put your Google Maps API key in the following 2 URIs, it will be needed to
	work on you domain -->
    <script src="http://www.google.com/uds/api?file=uds.js&amp;v=1.0&amp;key=ABQIAAAAmliIaHLYyQ5UIRjBd9vuaBSmxzlquxT2cBit4loLrA8bQGbmlxSziDS3DEAVuU-s-rSgW4KKef-2sg" type="text/javascript"></script>
	<script src="http://maps.google.com/maps?file=api&v=2.x&key=ABQIAAAAmliIaHLYyQ5UIRjBd9vuaBSmxzlquxT2cBit4loLrA8bQGbmlxSziDS3DEAVuU-s-rSgW4KKef-2sg" type="text/javascript"></script>
    
	<script src="prototype.js" type="text/javascript"></script>
    <script language="Javascript" type="text/javascript"> 
    
        //<![CDATA[
    
/*  
Places To Go, version 2.0
            
The HPL License
           
Copyright (c) 2007 Ron Pastore <vacorama@gmail.com>, ATJI, LLC
www.atji.net
		

Redistribution and use in source and binary forms, with or without 
modification, are permitted provided that the following conditions 
are met:

    * Redistributions of source code must retain the above copyright notice, 
      this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation
      and/or other materials provided with the distribution.
    * Using this software in source or binary format, with or without 
      modification, to develop, modify or improve products with an intended 
      purpose of causing bodily harm to humans, without their consent, 
      or of causing grievous bodily harm to any other animal from the phylum 
      Chordata (including, but not limited to, all mammals, fishes and birds), 
      is not permitted without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS IS" AND 
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
    
        var map;
        var geocoder;
        var directions;
        var searchControl;
        var streetAddressArray = new Array();
        var startingPoint = false;	
		var totalDistance;
		var shortest_total_meters_yet = 0;
		var current_permutation_index = 0;
		var best_permutation = false;
		var doing_route_calculation = false;
        var permutation_json = false;
		var permutation_counter = 0;
		var max_permutaion_amount = 0;
		//var run_mode = 'verbose';
		
		var run_mode = 'quite';
		var hide_itinerary = false;
		
		function testAlert(message){
			if (run_mode == 'verbose') {
				alert(message);
			}
			
			
		}
        
		//how do i set this?
        //_UDS_MSG_SEARCHCONTROLCOPY = "Add Place"; 
        function getBestRoute() {
            
			max_permutaion_amount = getMaxPermutations(streetAddressArray.length);
			$("progress_indication").show();
			$("main_workspace").hide();
			
			doing_route_calculation = true;
			hide_itinerary = true;	
			
			new Ajax.Request('get_max_permutations.php?number_perms=' + streetAddressArray.length, {
			  method:'get',
			  requestHeaders: {Accept: 'application/json'},
			  onSuccess: function(transport){
			    
				permutation_json = transport.responseText.evalJSON().array_of_perms;
				loadNextPermutation();							
			  }				  
			});
        }
		
		function loadNextPermutation() {
			if (!permutation_json[current_permutation_index]) {
				$("main_workspace").show();
				$("progress_indication").hide();			
				testAlert("done");
				testAlert("best perm" + best_permutation);
				
				hide_itinerary = false;
				
				bestStreetAddressArray = Array();
				for (x in best_permutation) {
					streetArrayIndex = best_permutation[x];
					if (typeof(streetArrayIndex) != 'number') {
						continue;
					}
					bestStreetAddressArray.push(streetAddressArray[streetArrayIndex]);
				}
				
				streetAddressArray = bestStreetAddressArray;
				testAlert("best array" + streetAddressArray);				
				
				doing_route_calculation = false;
				showDirections();
			
			} else {
			
				permutation_counter = permutation_counter +1;
				$("progress_indication").innerHTML = "<h4>Calculating " + permutation_counter + " of " + max_permutaion_amount + " Possible Routes</h4>";
				streetAddressArrayForCalc = Array();
				for (x in permutation_json[current_permutation_index]) {
					streetArrayIndex = permutation_json[current_permutation_index][x];
					if (typeof(streetArrayIndex) != 'number') {
						continue;
					}
					streetAddressArrayForCalc.push(streetAddressArray[streetArrayIndex]);
				}
				testAlert(streetAddressArrayForCalc);			
				showDirections();
			}
		}
		
        function OnLoad() {
			$("progress_indication").hide();
            $('Itinerary').hide();
            $('TotalDistance').hide();
            $('Map').hide();
            $('IsSearchResultCorrect').hide();  
            $('AddPlace').hide();
        }
        
        function showDirections() {
            $('Directions').innerHTML = "";              
            directionsPanel = $('Directions');
			
			if (hide_itinerary) {
				directions = new GDirections(map);
			} else {
				map = new GMap2($('Map'));
				directions = new GDirections(map, directionsPanel);
			}
            GEvent.addListener(directions, "load", onGDirectionsLoad);
           
			if (doing_route_calculation) {
				streetAddressArrayPlusStartingPoint = new Array(startingPoint).concat(streetAddressArrayForCalc);
			} else {
				streetAddressArrayPlusStartingPoint = new Array(startingPoint).concat(streetAddressArray);
			}
			
			//make sure our starting address is where we return to... 
			streetAddressArrayPlusStartingPoint.push(startingPoint);
			directions.loadFromWaypoints(streetAddressArrayPlusStartingPoint);
        }
        
        function onGDirectionsLoad() {
			testAlert("total distance" + directions.getDistance().meters);
			if (doing_route_calculation) {
				if (shortest_total_meters_yet == 0) {
					shortest_total_meters_yet = directions.getDistance().meters;
				}
				if (directions.getDistance().meters <= shortest_total_meters_yet) {
					best_permutation = permutation_json[current_permutation_index];
					shortest_total_meters_yet = directions.getDistance().meters;
				}
				current_permutation_index = current_permutation_index + 1;
				
				testAlert("shortest yet" + shortest_total_meters_yet);
				
				/* the timeout makes sure the browser gets to breath in between requests, avoiding 'busy script'
				 * messages
				 */ 
				setTimeout("loadNextPermutation()", 50);
			}
			else {
				$('Miles').innerHTML = directions.getDistance().html;				
				$('Itinerary').show();
				$('TotalDistance').show();
			}
        }
        
        function searchByZipAndBusiness(zip, Business) {
            var searchControl = new GSearchControl();
            localSearch = new GlocalSearch();
            searchControl.addSearcher(localSearch);
            localSearch.setCenterPoint(zip);
            searchControl.setOnKeepCallback(this, getAddressHandler);             
            searchControl.draw($("SearchResult"));
            searchControl.execute(Business);
            
            $('SearchResult').show();            
            $('IsSearchResultCorrect').show();
        }
        
        function getAddressHandler(result) {
            streetAddressArray.push(result.streetAddress + "," + result.city + "," + result.region);   
            isSearchResultCorrect(1);
        }
        
        //if not correct, let user try again...
        function isSearchResultCorrect(tinyInt) {
            if (tinyInt == 1) {
                PlaceAddedNowCleanupPage();
            } else {
                removeBadSearchResult();
            }    
        }
        
        function setStartingAddress(zip, address) {
            showAddress(address + "," + zip);
            //$('About').hide();
            $('AddPlace').show();
            $('Map').show();
            $('SetStartingAddress').innerHTML = "";
			startingPoint = address + "," + zip;
        }
        
        function PlaceAddedNowCleanupPage() {
            $('SearchResult').hide();
            $('IsSearchResultCorrect').hide();
            $('Directions').innerHTML = '';

            showDirections();
        }
        
        function removeBadSearchResult() {
            $('SearchResult').hide();
            $('IsSearchResultCorrect').hide();
        }    
        
        function showAddress(address) {
            var map = new GMap2($('Map'));
            var geocoder = new GClientGeocoder();
            geocoder.getLatLng(
              address,
              function(point) {
                if (!point) {
                  alert(address + " not found");
                } else {
                  map.setCenter(point, 13);
                  var marker = new GMarker(point);
                  map.addOverlay(marker);
                  marker.openInfoWindowHtml(address);
                }
              }
            );
        }
        
		
        function getMaxPermutations(num) {
            max = num;
            while ((num - 1) > 0 ) {
                max = max * (num - 1);
                num = num - 1; 
            }
            return max;
        }
        
		
        GSearch.setOnLoadCallback(OnLoad);
        //]]>
    
    </script>
  </head>


    
  <body>
    <h1>Places To Go</h1>
        <div id="About">
            <p>    
                 "Places To Go" is a brute force solution to the traveling salesman problem,
				 using a combination of Google Maps and Google Local Search APIs. It provides
				 the ability to enter various destinations, making up an itinerary. It will then 
				 calculate the best order to visit those destinations and return home while traveling the least
				 amount of miles.
				 
            </p>
			<p><i>"Places To Go" is freely distributable under the terms of the HPL (Harm-less Permissive) license. To obtain a copy 
			for your site, or to contribute to the project, visit <a href="http://code.google.com/p/places-to-go/">home page...</a></i></p>
        
		</div>
		<br />
		<div id="main_workspace">
	        <div id='SetStartingAddress'>
	            <p>
	                Address:  <input type="text" id="StartingAddress">
	                Zip: <input type="text" id="StartingZip" size="5">
	                <button onclick="setStartingAddress($('StartingZip').value, $('StartingAddress').value)" >Set Starting Address</button>
	            </p>
	        </div>
	        <table width="95%">
	            <tr>
	                <td id="left_side_map">
		               	
		                    <div id="AddPlace" class="AddPlace">
		                        <h1>Where to?</h1>
		                        <p>
		                            Address  or Business Name:<input type="text" id="Business">
		                            Zip:<input type="text" id="PlaceZip" size="5">
		                        </p>
		                        <button onclick="searchByZipAndBusiness(document.getElementById('PlaceZip').value, document.getElementById('Business').value)">Add Place</button>
		                    </div>
		                    <div id="SearchResult"></div>
				    		<div id="IsSearchResultCorrect">   
					    		<p>Click "Copy" if correct...</p>	    
		                        <button onclick="isSearchResultCorrect(false)">Not the right place?</button>
		                    </div>
		                    <div class="box" id="Map" style="width: 500px; height: 300px"></div>
						
	               </td>
	               <td>     
	                    <div id="TotalDistance">
	                        <h2>Total Distance:<span id="Miles"></span></h2>
	                    </div>
	    
	                    <div id="Itinerary">
	                        <div id="GetBestRoute">
	                            <button onclick="getBestRoute()">Calculate Best Route</button>
	                        </div>
	                        <h1>Itinerary</h1>
	                        <div id='Directions'>
	                        </div>
	                    </div>
	                </td>
	           </tr>
	       </table>
	   </div>
	   <div id="progress_indication"></div>
<script type="text/javascript">
		   var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
		   document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
	   </script>
	   <script type="text/javascript">
		   try {
			   var pageTracker = _gat._getTracker("UA-318355-3");
			   pageTracker._trackPageview();
		   } catch(err) {}
</script>
   
   </body>
</html>
